#ifndef _USART_HW_H_
#define _USART_HW_H_

#include "soc.h"

/**
 * USART支持多种协议格式：
 *    1. 局域互联网络(LIN);
 *    2. 智能卡协议(ISO7816);
 *    3. 红外线数据协议(IrDA) SIR ENDEC规范;
 *    4. 调制解调操作(CTS/RTS);
 *    5. 多处理器模式，如果地址不匹配进入静默模式，静默模式唤醒等;
 *    6. TX/RX可单独使能;
 */

typedef struct {
	_RW SR;         /*!< USART Status register,                   offset: 0x00 */
	_RW DR;         /*!< USART Data register,                     offset: 0x04 */
	_RW BRR;        /*!< USART Baud rate register,                offset: 0x08 */
	_RW CR1;        /*!< USART Control register 1,                offset: 0x0C */
	_RW CR2;        /*!< USART Control register 2,                offset: 0x10 */
	_RW CR3;        /*!< USART Control register 3,                offset: 0x14 */
	_RW GTPR;       /*!< USART Guard time and prescaler register, offset: 0x18 */
} USART_Struct;

extern USART_Struct SOC_USART1;  /* APB1时钟，最大42M */
extern USART_Struct SOC_USART2;
extern USART_Struct SOC_USART3;
extern USART_Struct SOC_UART4;
extern USART_Struct SOC_UART5;
extern USART_Struct SOC_USART6;  /* APB2时钟，最大84M */
extern USART_Struct SOC_UART7;
extern USART_Struct SOC_UART8;

/**
 * 状态寄存器，[7][4:0]为只读状态位，[9:8][6:5]可通过软件写0清0
 */
#define USART_SR_PE           (0x1U<<0)  /* 奇偶校验错误，读SR再读/写DR可
                                            清除 */
#define USART_SR_FE           (0x1U<<1)  /* 帧错误，读SR再读DR可清除 */
#define USART_SR_NF           (0x1U<<2)  /* 检测到噪声，读SR再读DR可清除 */
#define USART_SR_ORE          (0x1U<<3)  /* 接收上溢错误，读SR再读DR可清除 */
#define USART_SR_IDLE         (0x1U<<4)  /* 线路空闲，读SR再读DR可清除 */
#define USART_SR_RXNE         (0x1U<<5)  /* 接收到数据，读DR可清除，DMA模式下
                                            可写0清零 */
#define USART_SR_TC           (0x1U<<6)  /* 发送完成，读SR再写DR可清除，DMA
                                            模式下可写0清零 */
#define USART_SR_TXE          (0x1U<<7)  /* 发送为空，写DR可清除 */
#define USART_SR_LBD          (0x1U<<8)  /* LIN断路检测，软件写0清零 */
#define USART_SR_CTS          (0x1U<<9)  /* CTS状态发生变化，软件写0清零，
                                            不适用于UART4/5 */

/**
 * 数据寄存器，使能了奇偶校验位后，高位的奇偶校验位（7或8）由硬件填充，
 * 读取时可以读到接收的奇偶校验位
 */
#define USART_DR_0_1FH(val)   (val)

/**
 * 波特率，支持小数波特率，当TX/RX均禁止时，波特率计数器也会停止
 */
#define USART_BRR_MANTISSA_0_1023D(val) ((val)<<4)
#define USART_BRR_FRACTION_0_16D(val)   ((val)<<0) /* 当OVER8=1时，最大值为7 */

/**
 * 控制
 */
#define USART_CR1_SBK_DIS     (0x0U<<0)
#define USART_CR1_SBK_EN      (0x1U<<0)   /* 发送断路字符 */
#define USART_CR1_RWU_ACTIVE  (0x0U<<1)   /* 接收器处于活动模式 */
#define USART_CR1_RWU_QUIET   (0x1U<<1)   /* 接收器处于静音模式 */
#define USART_CR1_RE_DIS      (0x0U<<2)
#define USART_CR1_RE_EN       (0x1U<<2)   /* 接收器使能 */
#define USART_CR1_TE_DIS      (0x0U<<3)
#define USART_CR1_TE_EN       (0x1U<<3)   /* 发送器使能 */
#define USART_CR1_IDLEIE_DIS  (0x0U<<4)
#define USART_CR1_IDLEIE_EN   (0x1U<<4)   /* 线路空闲中断使能，当串口接收
                                             到1个字节后，如果第二个字节
                                             没有连续发送过来，就会产生
                                             一次IDLE事件 */
#define USART_CR1_RXNEIE_DIS  (0x0U<<5)   /* 使用DMA时应禁止该中断 */
#define USART_CR1_RXNEIE_EN   (0x1U<<5)   /* 接收中断使能 */
#define USART_CR1_TCIE_DIS    (0x0U<<6)
#define USART_CR1_TCIE_EN     (0x1U<<6)   /* 发送完成中断使能 */
#define USART_CR1_TXEIE_DIS   (0x0U<<7)
#define USART_CR1_TXEIE_EN    (0x1U<<7)   /* 发送为空中断使能 */
#define USART_CR1_PEIE_DIS    (0x0U<<8)
#define USART_CR1_PEIE_EN     (0x1U<<8)   /* 奇偶校验错误中断使能 */
#define USART_CR1_PS_NONE     (0x0U<<9)   /* 不校验 */
#define USART_CR1_PS_EVEN     (0x2U<<9)   /* 偶校验 */
#define USART_CR1_PS_ODD      (0x3U<<9)   /* 奇校验 */
#define USART_CR1_WAKE_IDLE   (0x0U<<11)  /* 通过空闲线路唤醒 */
#define USART_CR1_WAKE_ADDR   (0x1U<<11)  /* 通过地址标记唤醒 */
#define USART_CR1_M_8BIT      (0x0U<<12)  /* 数据位宽8bit */
#define USART_CR1_M_9BIT      (0x0U<<12)  /* 数据位宽9bit */
#define USART_CR1_UE_DIS      (0x0U<<13)
#define USART_CR1_UE_EN       (0x1U<<13)  /* 使能预分频器，可关闭以降低功耗 */
#define USART_CR1_OVER_8      (0x1U<<15)  /* 8倍采样，仅UART模式可用 */
#define USART_CR1_OVER_16     (0x0U<<15)  /* 16倍采样，其他模式强制为0 */

/**
 * 控制2
 */
#define USART_CR2_ADD_0_FH(val)  (((val)&0xF)<<0)  /* 多处理器通信时使用该域，
                                                      设置唤醒地址 */
#define USART_CR2_LBDL_10BIT  (0x0U<<5)   /* LIN 10位断路检测 */
#define USART_CR2_LBDL_11BIT  (0x1U<<5)   /* LIN 11位断路检测 */
#define USART_CR2_LBDIE_DIS   (0x0U<<6)
#define USART_CR2_LBDIE_EN    (0x1U<<6)   /* LIN断路检测中断使能 */
#define USART_CR2_LBCL_DIS    (0x0U<<6)
#define USART_CR2_LBCL_EN     (0x1U<<6)   /* 同步模式下，最后一个位的时钟在
                                             SCLK上输出，同步模式不适用
                                             UART4/5 */
#define USART_CR2_CPHA_FIRST  (0x0U<<9)   /* 在时钟变化的第一个时钟沿捕获
                                             数据 */
#define USART_CR2_CPHA_SECOND (0x1U<<9)   /* 在时钟变化的第二个时钟沿捕获
                                             数据 */
#define USART_CR2_CPOL_LOW    (0x0U<<10)  /* SCLK空闲时为低电平 */
#define USART_CR2_CPOL_HIGH   (0x1U<<10)  /* SCLK空闲时为高电平 */
#define USART_CR2_CLKEN_DIS   (0x0U<<11)
#define USART_CR2_CLKEN_EN    (0x1U<<11)  /* 启用SCLK */
#define USART_CR2_STOP_1      (0x0U<<12)  /* 1个停止位 */
#define USART_CR2_STOP_0_5    (0x1U<<12)  /* 0.5个停止位，用于智能卡，不适用
                                             UART4/5 */
#define USART_CR2_STOP_2      (0x2U<<12)  /* 2个停止位 */
#define USART_CR2_STOP_1_5    (0x3U<<12)  /* 1.5个停止位，用于智能卡，不适用
                                             UART4/5 */
#define USART_CR2_LINEN_DIS   (0x0U<<14)
#define USART_CR2_LINEN_EN    (0x1U<<14)  /* 启用LIN功能 */

/**
 * 控制3
 */
#define USART_CR3_EIE_DIS     (0x0U<<0)
#define USART_CR3_EIE_EN      (0x1U<<0)   /* DMA错误中断使能 */
#define USART_CR3_IREN_DIS    (0x0U<<1)
#define USART_CR3_IREN_EN     (0x1U<<1)   /* IrDA模式使能 */
#define USART_CR3_IRLP_DIS    (0x0U<<2)   /* IrDA正常模式 */
#define USART_CR3_IRLP_EN     (0x1U<<2)   /* IrDA低功耗使能 */
#define USART_CR3_HDSEL_DIS   (0x0U<<3)
#define USART_CR3_HDSEL_EN    (0x1U<<3)   /* 半双工模式使能 */
#define USART_CR3_NACK_DIS    (0x0U<<4)
#define USART_CR3_NACK_EN     (0x1U<<4)   /* 智能卡出现奇偶校验错误时发送
                                             NACK，不适用UART4/5 */
#define USART_CR3_SCEN_DIS    (0x0U<<5)
#define USART_CR3_SCEN_EN     (0x1U<<5)   /* 智能卡模式使能 */
#define USART_CR3_DMAR_DIS    (0x0U<<6)
#define USART_CR3_DMAR_EN     (0x1U<<6)   /* DMA接收使能 */
#define USART_CR3_DMAT_DIS    (0x0U<<7)
#define USART_CR3_DMAT_EN     (0x1U<<7)   /* DMA发送使能 */
#define USART_CR3_RTSE_DIS    (0x0U<<8)
#define USART_CR3_RTSE_EN     (0x1U<<8)   /* RTS使能，当接收缓冲区有空间时才
                                             会请求数据，RTS输出低，不适用
                                             UART4/5 */
#define USART_CR3_CTSE_DIS    (0x0U<<9)
#define USART_CR3_CTSE_EN     (0x1U<<9)   /* CTS使能，仅当CTS有效（输入低电
                                             平）才发送数据 */
#define USART_CR3_CTSIE_DIS   (0x0U<<10)
#define USART_CR3_CTSIE_EN    (0x1U<<10)  /* CTS中断使能 */
#define USART_CR3_ONEBIT_DIS  (0x0U<<11)
#define USART_CR3_ONEBIT_EN   (0x1U<<11)  /* 一个采样位，将禁止噪声检测 */

/**
 * 保护时间和预分频，保护时间以波特率为计时单位，在智能卡模式下使用。
 * 预分频：
 *     1. 在IrDA正常模式下，PSC必须为1;
 *     2. 在IrDA低功耗模式下，0 < PSC < 256，对应到1~255分频
 *     3. 在智能卡模式下，0 < PSC < 32，对应到2~64分频
 */
#define USART_GTPR_PSC_0_255D(val)  ((val)<<0)
#define USART_GTPR_GT_0_255D(val)   ((val)<<8)

#endif /* _USART_HW_H_ */
